feat(csharp): make core ADBC and trace listeners AOT-compatible to support standalone C# drivers#4243
feat(csharp): make core ADBC and trace listeners AOT-compatible to support standalone C# drivers#4243CurtHagenlocher wants to merge 3 commits intoapache:mainfrom
Conversation
Adds net10.0 to the target frameworks for Apache.Arrow.Adbc and the
trace-listener assembly, with <IsAotCompatible>true</IsAotCompatible>
enabled on that TFM.
- Replace FileVersionInfo.GetVersionInfo(assembly.Location) with
AssemblyInformationalVersionAttribute lookup; Assembly.Location is
empty under single-file publish. A guarded FileVersionInfo fallback
is retained for JIT via RuntimeFeature.IsDynamicCodeSupported.
- Rewrite IArrowArrayExtensions.SerializeToJson to dispatch through
Utf8JsonWriter instead of the reflection-based JsonSerializer. Every
value type ParseStructArray can produce is dispatched explicitly.
SqlDecimal (Decimal128) now emits as a JSON number when the declared
precision is <= 15 and as a string otherwise, replacing the previous
accidental {IsNull, Value, Precision, ...} shape.
- Rewrite FileListener.ActivityProcessor to serialize via a source-
generated JsonSerializerContext. A new OtelAttributesConverter
preserves OpenTelemetry-compatible attribute values (string, bool,
int64, double, and homogeneous arrays) as native JSON; non-OTel
values fall back to invariant-culture strings so the output doesn't
drift by locale.
- CAdbcDriverExporter.AdbcDriverInit returns NotImplemented rather
than InternalError for unsupported ADBC versions so the importer's
1.1.0 -> 1.0.0 fallback works.
- Add InternalsVisibleTo for Apache.Arrow.Adbc.Testing (the actual
assembly name; the existing Apache.Arrow.Adbc.Tests entry is stale).
Covered by 27 new golden-output tests for SerializeToJson and 14 new
tests for OtelAttributesConverter (including invariant-culture
verification under a non-English locale).
There was a problem hiding this comment.
Pull request overview
This PR updates the C# ADBC core and telemetry trace listener code to be AOT-friendly (including single-file publish), primarily by avoiding reflection-based JSON serialization and Assembly.Location-dependent version lookups, and by adding a new TFM intended for AOT scenarios.
Changes:
- Add
net10.0target framework (withIsAotCompatible=true) forApache.Arrow.Adbcand the telemetry listeners assembly. - Replace reflection-based JSON serialization with
Utf8JsonWriter(struct-to-JSON) and source-generatedSystem.Text.Jsoncontext (trace file listener), including new OTel attribute converters. - Adjust ADBC driver init status code for unsupported versions and update
InternalsVisibleTofor the correct testing assembly.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| csharp/src/Apache.Arrow.Adbc/Apache.Arrow.Adbc.csproj | Adds net10.0 TFM and marks it AOT-compatible. |
| csharp/src/Telemetry/Traces/Listeners/Apache.Arrow.Adbc.Telemetry.Traces.Listeners.csproj | Adds net10.0 TFM and marks it AOT-compatible. |
| csharp/src/Apache.Arrow.Adbc/Tracing/ActivityTrace.cs | Switches assembly version retrieval to informational attribute + guarded file version fallback. |
| csharp/src/Apache.Arrow.Adbc/Extensions/IArrowArrayExtensions.cs | Rewrites struct-to-JSON serialization to use Utf8JsonWriter with explicit type dispatch. |
| csharp/test/Apache.Arrow.Adbc.Tests/SerializeStructToJsonTests.cs | Adds golden-output tests for the new struct-to-JSON serialization output. |
| csharp/src/Telemetry/Traces/Listeners/FileListener/ActivityProcessor.cs | Uses source-generated JSON serialization for activities on NET6_0_OR_GREATER. |
| csharp/src/Telemetry/Traces/Listeners/FileListener/TraceJsonContext.cs | Introduces JsonSerializerContext for source-generated trace JSON. |
| csharp/src/Telemetry/Traces/Listeners/FileListener/SerializableActivity.cs | Adds JSON converters for activity tag payloads to preserve OTel-compatible shapes. |
| csharp/src/Telemetry/Traces/Listeners/FileListener/OtelAttributesConverter.cs | Implements converters + writer to emit OTel-native JSON scalars/arrays and invariant-string fallbacks. |
| csharp/test/Telemetry/Traces/Listeners/FileListener/OtelAttributesConverterTests.cs | Adds tests for OTel attribute JSON emission and locale-invariant fallbacks. |
| csharp/src/Apache.Arrow.Adbc/C/CAdbcDriverExporter.cs | Returns NotImplemented for unsupported ADBC versions to enable importer fallback behavior. |
| csharp/src/Apache.Arrow.Adbc/Properties/AssemblyInfo.cs | Adds InternalsVisibleTo for Apache.Arrow.Adbc.Testing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…e C# with a test fixture driver.
| name: "C# NativeAOT smoke test (windows-2022)" | ||
| runs-on: windows-2022 | ||
| # if: ${{ !contains(github.event.pull_request.title, 'WIP') }} | ||
| if: false |
There was a problem hiding this comment.
Disabled for now
| } | ||
|
|
||
| [Fact] | ||
| public void Decimal128_NarrowPrecision_AsNumber() |
There was a problem hiding this comment.
@davidhcoe, decimal128 values were previously being JSON-converted to something like {"IsNull":false,"Value":123.45,"IsPositive":true,"Precision":10,"Scale":2,"Data":[12345,0,0,0],"BinData":"OTAAAAAAAAAAAAAAAAAAAA=="} because that's how JsonSerializer translates SqlDecimal. I've taken the liberty of making this breaking change in the output because I can't imagine that anyone was making use of that. Feel free to raise an objection.
| # link.exe step can find link.exe/lib.exe and the Windows SDK. | ||
| # The existing workflow only uses first-party actions, so flag | ||
| # this for review before enabling. | ||
| uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1 |
There was a problem hiding this comment.
Seems to be fairly widely used and hasn't been changed in a while. (This was a Claude suggestion.)
| public string? ParentSpanId { get; set; } | ||
| public string? IdFormat { get; set; } | ||
|
|
||
| [JsonConverter(typeof(OtelAttributesDictionaryConverter))] |
Adds net10.0 to the target frameworks for Apache.Arrow.Adbc and the trace-listener assembly, with
<IsAotCompatible>true</IsAotCompatible>enabled on that TFM.Replace
FileVersionInfo.GetVersionInfo(assembly.Location)withAssemblyInformationalVersionAttributelookup;Assembly.Locationis empty under single-file publish. A guardedFileVersionInfofallback is retained for JIT viaRuntimeFeature.IsDynamicCodeSupported.Rewrite
IArrowArrayExtensions.SerializeToJsonto dispatch throughUtf8JsonWriterinstead of the reflection-basedJsonSerializer. Every value typeParseStructArraycan produce is dispatched explicitly.SqlDecimal(Decimal128) now emits as a JSON number when the declared precision is <= 15 and as a string otherwise, replacing the previous accidental {IsNull, Value, Precision, ...} shape.Rewrite
FileListener.ActivityProcessorto serialize via a source-generatedJsonSerializerContext. A newOtelAttributesConverterpreserves OpenTelemetry-compatible attribute values (string, bool, int64, double, and homogeneous arrays) as native JSON; non-OTel values fall back to invariant-culture strings so the output doesn't drift by locale.CAdbcDriverExporter.AdbcDriverInitreturnsNotImplementedrather thanInternalErrorfor unsupported ADBC versions so the importer's 1.1.0 -> 1.0.0 fallback works.Add
InternalsVisibleTofor Apache.Arrow.Adbc.Testing (the actual assembly name; the existing Apache.Arrow.Adbc.Tests entry is stale).Covered by 27 new golden-output tests for
SerializeToJson, 14 new tests forOtelAttributesConverter(including invariant-culture verification under a non-English locale) and 4 new tests for the driver exporter.